package com.shsoft.controller;

import com.alibaba.fastjson.JSONObject;
import com.shsoft.MonitorApplication;
import com.shsoft.component.TextComponent;
import com.shsoft.component.*;
import com.shsoft.config.PCStatusConstant;
import com.shsoft.entity.HardWareInfo;
import com.shsoft.entity.HefengQueryCityInfo;
import com.shsoft.serial.SerialPortManager;
import com.shsoft.task.WeatherTask;
import com.shsoft.util.FileUtil;
import gnu.io.SerialPort;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import okhttp3.*;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.List;
import java.util.*;

public class MainController implements Initializable {

    private double offsetX,offsetY,baseX,baseY,baseWidth,baseHeight;

    public Alert loading;

    private String currentTemplateName;

    private BaseComponent currentComponent;

    public ArrayList<BaseComponent> componentList;

    public ArrayList<BaseComponent> communicationComponentList;

    public Map<String, WritableImage> componentBaseImageMap;

    private Font iconFont;

    public Map<String, Font> fontMap;

    @FXML
    private VBox root,customZone,textComponentZone,imageComponentZone,shapeComponentZone,barComponentZone,dataComponentZone,animComponentZone;
    @FXML
    private AnchorPane moveDiv,canvasZone;
    @FXML
    private Label minBtn,closeBtn,cpuName,gpuName,memName,customZoneLabel,templateName,shapeComponentHeightLabel,shapeComponentWidthLabel,shapeComponentArcLabel,shapeComponentLineWidthLabel,barComponentBorderWidthLabel;
    @FXML
    private TextField cpuUsageCur,cpuUsageMin,cpuUsageMax,cpuTempCur,cpuTempMin,cpuTempMax,cpuClockCur,cpuClockMin,cpuClockMax,cpuPowerCur,cpuPowerMin,cpuPowerMax;
    @FXML
    private TextField gpuUsageCur,gpuUsageMin,gpuUsageMax,gpuTempCur,gpuTempMin,gpuTempMax,gpuClockCur,gpuClockMin,gpuClockMax,gpuPowerCur,gpuPowerMin,gpuPowerMax;
    @FXML
    private TextField memUsed,memClock,netUploadSpeed,netDownloadSpeed,weatherKey,cityName,cityID,textComponentContent,textComponentFontSize,textComponentX,textComponentY;
    @FXML
    private TextField imageComponentWidth,imageComponentHeight,imageComponentX,imageComponentY,imageComponentPath,shapeComponentArc,shapeComponentLineWidth,shapeComponentY,shapeComponentX,shapeComponentWidth,shapeComponentHeight;
    @FXML
    private TextField dataComponentName,dataComponentX,dataComponentY,barComponentBorderWidth,barComponentArc,barComponentX,barComponentY,barComponentWidth,barComponentHeight,barComponentName,dataComponentFontSize;
    @FXML
    private TextField animComponentWidth,animComponentHeight,animComponentInterval,animComponentX,animComponentY,animComponentFrames;
    @FXML
    private CheckBox autoStart,autoLight,systemTray,textComponentStroke,imageComponentStretch,dataComponentUnit;
    @FXML
    private ComboBox<String> themeChoose,comChoose,textComponentFontName,shapeComponentType,dataComponentFontName,barComponentDirection,dataComponentAlignment,textComponentAlignment,barComponentStyle;
    @FXML
    private Canvas baseCanvas,drawCanvas,moveCanvas;
    @FXML
    private ColorPicker colorChoose,textComponentFillColor,textComponentStrokeColor,shapeComponentColor,dataComponentFillColor,barComponentBorderColor,barComponentBarColor;
    @FXML
    private Button comBtn,comRefreshBtn,synchronousScreenBtn,saveTemplateBtn,removeComponentBtn,preComponentBtn,nextComponentBtn,topComponentBtn,bottomComponentBtn;
    @FXML
    private Slider lightSlider;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        try {
            componentList = new ArrayList<>();
            communicationComponentList = new ArrayList<>();
            componentBaseImageMap = new HashMap<>();
            fontMap = new HashMap<>();
            iconFont = Font.loadFont(new FileInputStream(MonitorApplication.projectPath + "\\data\\font\\iconfont.ttf"), 14);
            DropShadow shadow = new DropShadow(8, new Color(0, 0, 0, 1));
            root.setEffect(shadow);
            HardWareInfo.cityName = MonitorApplication.settingConfig.getCityName();
            initTitle();
            initOption();
            initScreen();
            if(!StringUtils.isEmpty(MonitorApplication.settingConfig.getTemplateName())){
                FileInputStream fileInputStream = new FileInputStream(FileUtil.getTemplateComponents(MonitorApplication.settingConfig.getTemplateName()));
                ObjectInputStream in = new ObjectInputStream(fileInputStream);
                communicationComponentList = getCommunicationComponentList((ArrayList<BaseComponent>) in.readObject());
                in.close();
                fileInputStream.close();
                File file = new File(FileUtil.getTemplateTotalImage(MonitorApplication.settingConfig.getTemplateName()));
                if(file.exists()){
                    BufferedImage image = ImageIO.read(file);
                    for (BaseComponent component : communicationComponentList) {
                        if (component.getType() == BaseComponent.ComponentType.BAR){
                            BarComponent barComponent = (BarComponent) component;
                            WritableImage writableImage = SwingFXUtils.toFXImage(image.getSubimage(barComponent.getBorderX(), barComponent.getBorderY(), barComponent.getTotalWidth(), barComponent.getTotalHeight()), new WritableImage(barComponent.getTotalWidth(), barComponent.getTotalHeight()));
                            componentBaseImageMap.put(PCStatusConstant.PRE_BAR_COMPONENT + barComponent.getName(), writableImage);
                        }
                        if (component.getType() == BaseComponent.ComponentType.DATA){
                            DataComponent dataComponent = (DataComponent) component;
                            WritableImage writableImage = SwingFXUtils.toFXImage(image.getSubimage(dataComponent.getBorderX(), dataComponent.getBorderY(), dataComponent.getBorderWidth(), dataComponent.getBorderHeight()), new WritableImage(dataComponent.getBorderWidth(), dataComponent.getBorderHeight()));
                            componentBaseImageMap.put(PCStatusConstant.PRE_DATA_COMPONENT + dataComponent.getName(), writableImage);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /////////////////////////////////////////////////初始化/////////////////////////////////////////////////////////////////

    private void initTitle(){
        moveDiv.setOnMousePressed(e ->{
            offsetX = e.getSceneX();
            offsetY = e.getSceneY();
        });
        moveDiv.setOnMouseDragged(e -> {
            Stage stage = (Stage) root.getScene().getWindow();
            Platform.runLater(() -> {
                stage.setX(e.getScreenX() - offsetX);
                stage.setY(e.getScreenY() - offsetY);
            });

        });
        minBtn.setFont(iconFont);
        closeBtn.setFont(iconFont);
        minBtn.setOnMouseClicked(e -> {
            Stage stage = (Stage) root.getScene().getWindow();
            stage.setIconified(true);
        });
        closeBtn.setOnMouseClicked(e -> {
            Stage stage = (Stage) root.getScene().getWindow();
            stage.close();
            Runtime.getRuntime().exit(0);
        });
    }

    private void initOption(){
        if(MonitorApplication.settingConfig.getTheme().equals(PCStatusConstant.THEME_DARK)){
            MonitorApplication.cssUrl = getClass().getClassLoader().getResource("css/dark.css");
        }else if(MonitorApplication.settingConfig.getTheme().equals(PCStatusConstant.THEME_LIGHT)){
            MonitorApplication.cssUrl = getClass().getClassLoader().getResource("css/light.css");
        }
        lightSlider.setMax(200);
        lightSlider.setMin(1);
        lightSlider.setValue(MonitorApplication.settingConfig.getLight());
        if(MonitorApplication.settingConfig.isAutoLight()){
            lightSlider.setDisable(true);
            autoLight.setSelected(true);
        }else {
            lightSlider.setDisable(false);
            autoLight.setSelected(false);
        }
        if(MonitorApplication.settingConfig.isSystemTray()){
            systemTray.setSelected(true);
        }
        if(MonitorApplication.settingConfig.isAutoStart()){
            autoStart.setSelected(true);
        }
        themeChoose.setItems(FXCollections.observableArrayList("浅色", "深色"));
        if(MonitorApplication.settingConfig.getTheme().equals(PCStatusConstant.THEME_DARK)){
            themeChoose.setValue("深色");
        }else if(MonitorApplication.settingConfig.getTheme().equals(PCStatusConstant.THEME_LIGHT)){
            themeChoose.setValue("浅色");
        }
        weatherKey.setText(MonitorApplication.settingConfig.getKey());
        cityName.setText(MonitorApplication.settingConfig.getCityName());
        cityID.setText(MonitorApplication.settingConfig.getCityID());
        colorChoose.setValue(Color.BLACK);
        List<String> ports = SerialPortManager.findPorts();
        if(null != ports && ports.size() > 0){
            comChoose.setItems(FXCollections.observableArrayList(ports));
        }
        if(!MonitorApplication.settingConfig.getPort().equals("")){
            try {
                MonitorApplication.serialport = SerialPortManager.openPort(MonitorApplication.settingConfig.getPort(), PCStatusConstant.BAUD_RATE);
                if(MonitorApplication.serialport != null){
                    comBtn.setText("断开");
                    comChoose.getSelectionModel().select(MonitorApplication.settingConfig.getPort());
                    comChoose.setDisable(true);
                    addSerialListener(MonitorApplication.serialport);
                }
            } catch (Exception e) {
                System.out.println("自动开启设备" + MonitorApplication.settingConfig.getPort() + "失败");
            }
        }
        themeChoose.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            String s = "";
            if(newValue.equals("浅色")){
                s = PCStatusConstant.THEME_LIGHT;
                MonitorApplication.settingConfig.setTheme(PCStatusConstant.THEME_LIGHT);
                MonitorApplication.cssUrl = getClass().getClassLoader().getResource("css/light.css");
            }else {
                s = PCStatusConstant.THEME_DARK;
                MonitorApplication.settingConfig.setTheme(PCStatusConstant.THEME_DARK);
                MonitorApplication.cssUrl = getClass().getClassLoader().getResource("css/dark.css");
            }
            changeTheme();
            try {
                FileUtil.updateKey("theme", s);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    private void initScreen(){
        List<String> fontList = FileUtil.getFontList();
        shapeComponentType.setItems(FXCollections.observableArrayList(PCStatusConstant.SHAPE_LINE, PCStatusConstant.SHAPE_FILL_RECT,PCStatusConstant.SHAPE_FILL_OVAL,PCStatusConstant.SHAPE_STROKE_RECT,PCStatusConstant.SHAPE_STROKE_OVAL));
        shapeComponentType.setValue(PCStatusConstant.SHAPE_STROKE_RECT);
        shapeComponentArcLabel.setVisible(true);
        shapeComponentArc.setVisible(true);
        shapeComponentLineWidthLabel.setVisible(true);
        shapeComponentLineWidth.setVisible(true);
        shapeComponentType.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if(shapeComponentType.getValue().equals(PCStatusConstant.SHAPE_LINE)){
                shapeComponentWidthLabel.setText("终点坐标  X");
                shapeComponentHeightLabel.setText("Y");
            }else {
                shapeComponentWidthLabel.setText("宽度");
                shapeComponentHeightLabel.setText("高度");
            }
            if(shapeComponentType.getValue().equals(PCStatusConstant.SHAPE_FILL_RECT) || shapeComponentType.getValue().equals(PCStatusConstant.SHAPE_STROKE_RECT)){
                shapeComponentArcLabel.setVisible(true);
                shapeComponentArc.setVisible(true);
            }else {
                shapeComponentArcLabel.setVisible(false);
                shapeComponentArc.setVisible(false);
            }
            if(shapeComponentType.getValue().equals(PCStatusConstant.SHAPE_STROKE_RECT) || shapeComponentType.getValue().equals(PCStatusConstant.SHAPE_STROKE_OVAL) || shapeComponentType.getValue().equals(PCStatusConstant.SHAPE_LINE)){
                shapeComponentLineWidthLabel.setVisible(true);
                shapeComponentLineWidth.setVisible(true);
            }else {
                shapeComponentLineWidthLabel.setVisible(false);
                shapeComponentLineWidth.setVisible(false);
            }
        });
        textComponentAlignment.setItems(FXCollections.observableArrayList(PCStatusConstant.ALIGNMENT_LEFT, PCStatusConstant.ALIGNMENT_CENTER,PCStatusConstant.ALIGNMENT_RIGHT));
        textComponentAlignment.setValue(PCStatusConstant.ALIGNMENT_LEFT);
        textComponentFontName.setItems(FXCollections.observableArrayList(fontList));
        textComponentFontName.setValue("思源宋体");
        textComponentFontSize.setText("20");
        dataComponentAlignment.setItems(FXCollections.observableArrayList(PCStatusConstant.ALIGNMENT_LEFT, PCStatusConstant.ALIGNMENT_CENTER,PCStatusConstant.ALIGNMENT_RIGHT));
        dataComponentAlignment.setValue(PCStatusConstant.ALIGNMENT_LEFT);
        dataComponentFontName.setItems(FXCollections.observableArrayList(fontList));
        dataComponentFontName.setValue("思源宋体");
        dataComponentFontSize.setText("20");
        barComponentStyle.setItems(FXCollections.observableArrayList(PCStatusConstant.BAR_STYLE_1, PCStatusConstant.BAR_STYLE_2));
        barComponentStyle.setValue(PCStatusConstant.BAR_STYLE_2);
        barComponentStyle.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if(barComponentStyle.getValue().equals(PCStatusConstant.BAR_STYLE_1)){
                barComponentBorderWidth.setVisible(true);
                barComponentBorderWidthLabel.setVisible(true);
                barComponentBorderWidth.setText("1");
            }else {
                barComponentBorderWidth.setVisible(false);
                barComponentBorderWidthLabel.setVisible(false);
            }
        });
        barComponentBorderWidth.setText("1");
        barComponentDirection.setItems(FXCollections.observableArrayList(PCStatusConstant.BAR_DIRECTION_H,PCStatusConstant.BAR_DIRECTION_V));
        barComponentDirection.setValue(PCStatusConstant.BAR_DIRECTION_H);
        barComponentArc.setText("15");
        barComponentBarColor.setValue(Color.GREENYELLOW);
        barComponentWidth.setText("100");
        barComponentHeight.setText("15");
        barComponentBorderWidth.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                barComponentBorderWidth.setText(oldText);
            }
        });
        barComponentArc.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                barComponentArc.setText(oldText);
            }
        });
        barComponentX.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                barComponentX.setText(oldText);
            }
        });
        barComponentY.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                barComponentY.setText(oldText);
            }
        });
        barComponentWidth.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                barComponentWidth.setText(oldText);
            }
        });
        barComponentHeight.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                barComponentHeight.setText(oldText);
            }
        });
        textComponentFontSize.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                textComponentFontSize.setText(oldText);
            }
        });
        textComponentX.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                textComponentX.setText(oldText);
            }
        });
        textComponentY.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                textComponentY.setText(oldText);
            }
        });
        imageComponentX.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                imageComponentX.setText(oldText);
            }
        });
        imageComponentY.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                imageComponentY.setText(oldText);
            }
        });
        imageComponentHeight.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                imageComponentHeight.setText(oldText);
            }
        });
        imageComponentWidth.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                imageComponentWidth.setText(oldText);
            }
        });
        shapeComponentArc.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                shapeComponentArc.setText(oldText);
            }
        });
        shapeComponentLineWidth.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                shapeComponentLineWidth.setText(oldText);
            }
        });
        shapeComponentX.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                shapeComponentX.setText(oldText);
            }
        });
        shapeComponentY.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                shapeComponentY.setText(oldText);
            }
        });
        shapeComponentWidth.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                shapeComponentWidth.setText(oldText);
            }
        });
        shapeComponentHeight.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                shapeComponentHeight.setText(oldText);
            }
        });
        dataComponentX.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                dataComponentX.setText(oldText);
            }
        });
        dataComponentY.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                dataComponentY.setText(oldText);
            }
        });
        dataComponentFontSize.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                dataComponentFontSize.setText(oldText);
            }
        });
        animComponentWidth.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                animComponentWidth.setText(oldText);
            }
        });
        animComponentHeight.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                animComponentHeight.setText(oldText);
            }
        });
        animComponentInterval.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                animComponentInterval.setText(oldText);
            }
        });
        animComponentX.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                animComponentX.setText(oldText);
            }
        });
        animComponentY.textProperty().addListener((obs, oldText, newText) -> {
            if (!newText.matches("-?\\d*")) {
                animComponentY.setText(oldText);
            }
        });
        setSettingOptionsVisiable(false);
        showComponentZone(null);
    }


    //////////////////////////////////////////////模板相关/////////////////////////////////////////////////////////////

    @FXML
    void createTemplate(ActionEvent event) {
        if(!StringUtils.isEmpty(currentTemplateName)){
            loading = new Alert(Alert.AlertType.CONFIRMATION);
            loading.initOwner(root.getScene().getWindow());
            loading.setTitle("创建模板");
            loading.setHeaderText("");
            loading.setContentText("未保存的操作将丢失，确认创建新模板吗？");
            Optional<ButtonType> result = loading.showAndWait();
            if(result.isPresent() && result.get() == ButtonType.OK){
                createTemplate();
            }
        }else {
            createTemplate();
        }
    }

    @FXML
    void deleteTemplate(ActionEvent event) {
        List<String> list = FileUtil.getTemplateNames();
        if(list.size() > 0){
            ChoiceDialog<String> dialog = new ChoiceDialog<>("",list);
            dialog.initOwner(root.getScene().getWindow());
            dialog.initStyle(StageStyle.UTILITY);
            dialog.setTitle(" 删除模板");
            dialog.setHeaderText("");
            dialog.setGraphic(null);
            dialog.setContentText("");
            Optional<String> s = dialog.showAndWait();
            if(s.isPresent()) {
                String deleteName = s.get();
                if(StringUtils.isEmpty(deleteName)){
                    return;
                }
                if(PCStatusConstant.defaultTemplateNames.contains(deleteName)){
                    showWarning("默认模板不允许删除");
                }else {
                    File file = new File(FileUtil.getTemplatePath(deleteName));
                    boolean b = FileUtil.deleteDir(file);
                    if(!StringUtils.isEmpty(currentTemplateName) && currentTemplateName.equals(deleteName)){
                        currentTemplateName = "";
                        setSettingOptionsVisiable(false);
                        componentList = new ArrayList<>();
                        fontMap = new HashMap<>();
                        currentComponent = null;
                        showComponentZone(null);
                    }
                    if(b){
                        showRight("删除成功");
                    }else {
                        showWarning("模板数据清理失败");
                    }
                }
            }
        }else {
            showRight("没有模板可以删除");
        }
    }

    @FXML
    void openTemplate(ActionEvent event) {
        if(!StringUtils.isEmpty(currentTemplateName)){
            loading = new Alert(Alert.AlertType.CONFIRMATION);
            loading.initOwner(root.getScene().getWindow());
            loading.setTitle("打开模板");
            loading.setHeaderText("");
            loading.setContentText("未保存的操作将丢失，确认打开其他模板吗？");
            Optional<ButtonType> result = loading.showAndWait();
            if(result.isPresent() && result.get() == ButtonType.OK){
                openTemplate();
            }
        }else {
            openTemplate();
        }
    }

    @FXML
    void saveTemplate(ActionEvent event) {
        try {
            if(componentList.size() > 0){
                ArrayList<BaseComponent> list = getCoincidenceVerificationComponentList(componentList);
                for (BaseComponent baseComponent : componentList) {
                    if(baseComponent.getType() == BaseComponent.ComponentType.BAR){
                        BarComponent component = (BarComponent) baseComponent;
                        int i = component.getHeight() * component.getWidth() * 2;
                        if(i > PCStatusConstant.MAX_BYTES_COUNT){
                            showComponentZone(BaseComponent.ComponentType.BAR);
                            currentComponent = component;
                            fillComponentControl(component);
                            drawComponents(drawCanvas, true, null);
                            component.drawComponentBorder(drawCanvas);
                            showWarning("关联【" + component.getName() + "】的条形组件尺寸过大，请适当调整后再次保存");
                            return;
                        }
                        if(component.getBorderX() < 0 || component.getBorderY() < 0 || (component.getBorderX() + component.getTotalWidth()) > 480 || component.getBorderY() + component.getTotalHeight() > 320){
                            showComponentZone(BaseComponent.ComponentType.BAR);
                            currentComponent = component;
                            fillComponentControl(component);
                            drawComponents(drawCanvas, true, null);
                            component.drawComponentBorder(drawCanvas);
                            showWarning("关联【" + component.getName() + "】的条形组件超出屏幕，请适当调整后再次保存");
                            return;
                        }
                        for (BaseComponent testComponent : list) {
                            if(testComponent == component){
                                continue;
                            }
                            boolean left_top = testComponent.isMe(component.getBorderX(), component.getBorderY());
                            boolean right_top = testComponent.isMe(component.getBorderX() + component.getTotalWidth(), component.getBorderY());
                            boolean left_bottom = testComponent.isMe(component.getBorderX(), component.getBorderY() + component.getTotalHeight());
                            boolean right_bottom = testComponent.isMe(component.getBorderX() + component.getTotalWidth(), component.getBorderY() + component.getTotalHeight());
                            boolean center = testComponent.isMe(component.getBorderX() + component.getTotalWidth() / 2, component.getBorderY() + component.getTotalHeight() / 2);
                            if(left_top || right_top || left_bottom || right_bottom || center){
                                showComponentZone(BaseComponent.ComponentType.BAR);
                                currentComponent = component;
                                fillComponentControl(component);
                                drawComponents(drawCanvas, true, null);
                                component.drawComponentBorder(drawCanvas);
                                showWarning("关联【" + component.getName() + "】的条形组件与其他组件出现重叠，请适当调整后再次保存");
                                return;
                            }
                        }
                    }else if (baseComponent.getType() == BaseComponent.ComponentType.DATA){
                        DataComponent component = (DataComponent) baseComponent;
                        int i = component.getBorderWidth() * component.getBorderHeight() * 2;
                        if(i > PCStatusConstant.MAX_BYTES_COUNT){
                            showComponentZone(BaseComponent.ComponentType.DATA);
                            currentComponent = component;
                            fillComponentControl(component);
                            drawComponents(drawCanvas, true, null);
                            component.drawComponentBorder(drawCanvas);
                            showWarning("组件【" + component.getName() + "】尺寸过大，请适当调整后再次保存");
                            return;
                        }
                        if(component.getBorderX() < 0 || component.getBorderY() < 0 || (component.getBorderX() + component.getBorderWidth()) > 480 || component.getBorderY() + component.getBorderHeight() > 320){
                            showComponentZone(BaseComponent.ComponentType.DATA);
                            currentComponent = component;
                            fillComponentControl(component);
                            drawComponents(drawCanvas, true, null);
                            component.drawComponentBorder(drawCanvas);
                            showWarning("组件【" + component.getName() + "】超出屏幕，请适当调整后再次保存");
                            return;
                        }
                        for (BaseComponent testComponent : list) {
                            if(testComponent == component){
                                continue;
                            }
                            boolean left_top = testComponent.isMe(component.getBorderX(), component.getBorderY());
                            boolean right_top = testComponent.isMe(component.getBorderX() + component.getBorderWidth(), component.getBorderY());
                            boolean left_bottom = testComponent.isMe(component.getBorderX(), component.getBorderY() + component.getBorderHeight());
                            boolean right_bottom = testComponent.isMe(component.getBorderX() + component.getBorderWidth(), component.getBorderY() + component.getBorderHeight());
                            boolean center = testComponent.isMe(component.getBorderX() + component.getBorderWidth() / 2, component.getBorderY() + component.getBorderHeight() / 2);
                            if(left_top || right_top || left_bottom || right_bottom || center){
                                showComponentZone(BaseComponent.ComponentType.DATA);
                                currentComponent = component;
                                fillComponentControl(component);
                                drawComponents(drawCanvas, true, null);
                                component.drawComponentBorder(drawCanvas);
                                showWarning("组件【" + component.getName() + "】与其他组件出现重叠，请适当调整后再次保存");
                                return;
                            }
                        }
                    }
                }
            }
            File templateDir = new File(FileUtil.getTemplatePath(currentTemplateName));
            if(!templateDir.exists())templateDir.mkdirs();
            File imageDir = new File(templateDir, "images");
            File animDir = new File(templateDir, "anim");
            File tmpImageDir = new File(templateDir, "tmpImages");
            File tmpAnimDir = new File(templateDir, "tmpAnim");
            if(!tmpImageDir.exists())tmpImageDir.mkdirs();
            if(!tmpAnimDir.exists())tmpAnimDir.mkdirs();
            if(componentList.size() > 0){
                for (BaseComponent baseComponent : componentList) {
                    if(baseComponent.getType() == BaseComponent.ComponentType.IMAGE){
                        ImageComponent component = (ImageComponent) baseComponent;
                        String imageName = FileUtil.copyImage(component.getImagePath(), tmpImageDir.getAbsolutePath());
                        component.setImageName(imageName);
                        component.setImagePath(imageDir.getAbsolutePath() + "/" + imageName);
                    }
                }
            }
            FileUtil.deleteDir(imageDir);
            FileUtil.deleteDir(animDir);
            tmpImageDir.renameTo(imageDir);
            tmpAnimDir.renameTo(animDir);
            WritableImage image = baseCanvas.snapshot(null, null);
            File imageFile = new File(FileUtil.getTemplateBackImage(currentTemplateName));
            ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", imageFile);
            drawFixedComponents();
            image = baseCanvas.snapshot(null, null);
            ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", new File(FileUtil.getTemplateTotalImage(currentTemplateName)));
            FileOutputStream fileOutputStream = new FileOutputStream(FileUtil.getTemplateComponents(currentTemplateName));
            ObjectOutputStream out = new ObjectOutputStream(fileOutputStream);
            out.writeObject(componentList);
            out.close();
            fileOutputStream.close();
            FileUtil.copyBackImage(currentTemplateName);
            Image tmpImage = new Image(new File(FileUtil.getTmpBackImagePath()).toURI().toString());
            baseCanvas.getGraphicsContext2D().drawImage(tmpImage, 0, 0, tmpImage.getWidth(), tmpImage.getHeight(), 0, 0, PCStatusConstant.SCREEN_WIDTH ,PCStatusConstant.SCREEN_HEIGHT);
            showRight("保存成功");
        } catch (IOException e) {
            e.printStackTrace();
            showWarning("保存失败，请重试");
        }
    }

    private void createTemplate(){
        TextInputDialog dialog = new TextInputDialog();
        dialog.setTitle("创建模板");
        dialog.setContentText("模板名称");
        dialog.initOwner(root.getScene().getWindow());
        dialog.setGraphic(null);
        dialog.setHeaderText("");
        Button btn = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
        btn.addEventFilter(ActionEvent.ACTION, e -> {
            String text = dialog.getEditor().getText().trim();
            if(StringUtils.isEmpty(text)){
                e.consume();
                showWarning("请填写模板名称");
            }else {
                File file = new File(FileUtil.getTemplatePath(text));
                if(file.exists()){ // 文件夹已存在
                    e.consume();
                    showWarning("模板名称已存在");
                }else {
                    currentTemplateName = text;
                    setSettingOptionsVisiable(true);
                    templateName.setText(text);
                    componentList = new ArrayList<>();
                    fontMap = new HashMap<>();
                    GraphicsContext graphicsContext2D = baseCanvas.getGraphicsContext2D();
                    graphicsContext2D.setFill(colorChoose.getValue());
                    graphicsContext2D.fillRoundRect(0,0,PCStatusConstant.SCREEN_WIDTH,PCStatusConstant.SCREEN_HEIGHT,0,0);
                    drawComponents(drawCanvas, true, null);
                    moveCanvas.getGraphicsContext2D().clearRect(0, 0, moveCanvas.getWidth(), moveCanvas.getHeight());
                    currentComponent = null;
                    showComponentZone(null);
                }
            }
        });
        dialog.showAndWait();
    }

    private void openTemplate(){
        List<String> list = FileUtil.getTemplateNames();
        if(list.size() > 0){
            ChoiceDialog<String> dialog = new ChoiceDialog<>(list.get(0),list);
            dialog.initOwner(root.getScene().getWindow());
            dialog.initStyle(StageStyle.UTILITY);
            dialog.setTitle("选择模板");
            dialog.setHeaderText("");
            dialog.setGraphic(null);
            dialog.setContentText("");
            Optional<String> s = dialog.showAndWait();
            if(s.isPresent()) {
                currentTemplateName = s.get();
                try {
                    FileInputStream fileInputStream = new FileInputStream(FileUtil.getTemplateComponents(currentTemplateName));
                    ObjectInputStream in = new ObjectInputStream(fileInputStream);
                    componentList = (ArrayList<BaseComponent>) in.readObject();
                    in.close();
                    fileInputStream.close();
                    FileUtil.copyBackImage(currentTemplateName);
                    File file = new File(FileUtil.getTmpBackImagePath());
                    if(file.exists()){
                        Image image = new Image(file.toURI().toString());
                        baseCanvas.getGraphicsContext2D().drawImage(image, 0, 0, image.getWidth(), image.getHeight(), 0, 0, PCStatusConstant.SCREEN_WIDTH ,PCStatusConstant.SCREEN_HEIGHT);
                    }
                    drawComponents(drawCanvas, true, null);
                    moveCanvas.getGraphicsContext2D().clearRect(0, 0, moveCanvas.getWidth(), moveCanvas.getHeight());
                    currentComponent = null;
                    setSettingOptionsVisiable(true);
                    templateName.setText(currentTemplateName);
                } catch (IOException | ClassNotFoundException e) {
                    e.printStackTrace();
                    showWarning("模板文件损坏");
                    setSettingOptionsVisiable(false);
                    componentList = new ArrayList<>();
                    fontMap = new HashMap<>();
                    currentTemplateName = "";
                }
                showComponentZone(null);
            }
        }else {
            showWarning("找不到模板");
        }
    }

    @FXML
    void synchronousScreen(ActionEvent event) {
        MonitorApplication.passNormalData.set(false);
        MonitorApplication.priorityDataArray.clear();
        MonitorApplication.normalDataArray.clear();
        if(MonitorApplication.serialport == null){
            showWarning("副屏端口尚未连接");
            return;
        }
        File file = new File(FileUtil.getTemplateTotalImage(currentTemplateName));
        if(!file.exists()){
            showWarning("请先保存模板");
            return;
        }
        loading = new Alert(Alert.AlertType.INFORMATION);
        loading.initOwner(root.getScene().getWindow());
        loading.initStyle(StageStyle.TRANSPARENT);
        loading.getDialogPane().setPrefWidth(200);
        loading.setHeaderText("");
        loading.setContentText("处理中，请稍后...");
        loading.setGraphic(new ImageView("/image/loading.png"));
        Button btn = (Button) loading.getDialogPane().lookupButton(ButtonType.OK);
        btn.setDisable(true);
        btn.setText("OK");
        loading.show();
        try {
            FileUtil.updateKey("templateName", currentTemplateName);
            MonitorApplication.settingConfig.setTemplateName(currentTemplateName);
            FileInputStream fileInputStream = new FileInputStream(FileUtil.getTemplateComponents(MonitorApplication.settingConfig.getTemplateName()));
            ObjectInputStream in = new ObjectInputStream(fileInputStream);
            ArrayList<BaseComponent> components = (ArrayList<BaseComponent>) in.readObject();
            in.close();
            fileInputStream.close();
            communicationComponentList = getCommunicationComponentList(components);
            BufferedImage image = ImageIO.read(file);
            componentBaseImageMap = new HashMap<>();
            for (BaseComponent component : communicationComponentList) {
                if (component.getType() == BaseComponent.ComponentType.BAR){
                    BarComponent barComponent = (BarComponent) component;
                    WritableImage writableImage = SwingFXUtils.toFXImage(image.getSubimage(barComponent.getBorderX(), barComponent.getBorderY(), barComponent.getTotalWidth(), barComponent.getTotalHeight()), new WritableImage(barComponent.getTotalWidth(), barComponent.getTotalHeight()));
                    componentBaseImageMap.put(PCStatusConstant.PRE_BAR_COMPONENT + barComponent.getName(), writableImage);
                }
                if (component.getType() == BaseComponent.ComponentType.DATA){
                    DataComponent dataComponent = (DataComponent) component;
                    WritableImage writableImage = SwingFXUtils.toFXImage(image.getSubimage(dataComponent.getBorderX(), dataComponent.getBorderY(), dataComponent.getBorderWidth(), dataComponent.getBorderHeight()), new WritableImage(dataComponent.getBorderWidth(), dataComponent.getBorderHeight()));
                    componentBaseImageMap.put(PCStatusConstant.PRE_DATA_COMPONENT + dataComponent.getName(), writableImage);
                }
            }
            byte[] animMsg = FileUtil.getAnimMsg();
            MonitorApplication.priorityDataArray.offer(animMsg);
            FileUtil.doBackImageArrays(image);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @FXML
    void useBackColor(ActionEvent event) {
        Color value = colorChoose.getValue();
        GraphicsContext graphicsContext2D = baseCanvas.getGraphicsContext2D();
        graphicsContext2D.setFill(value);
        graphicsContext2D.fillRoundRect(0,0,PCStatusConstant.SCREEN_WIDTH,PCStatusConstant.SCREEN_HEIGHT,0,0);
    }


    @FXML
    void useBackImage(ActionEvent event) throws FileNotFoundException {
        FileChooser fc = new FileChooser();
        fc.setTitle("选择图片");
        FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("图片 ( .jpg  .jpeg  .png )", "*.jpg", "*.jpeg", "*.png");
        fc.getExtensionFilters().add(extFilter);
        File file = fc.showOpenDialog(root.getScene().getWindow());
        if (file != null) {
            Image image = new Image(file.toURI().toString());
            baseCanvas.getGraphicsContext2D().drawImage(image, 0, 0, image.getWidth(), image.getHeight(), 0, 0, PCStatusConstant.SCREEN_WIDTH ,PCStatusConstant.SCREEN_HEIGHT);
        }
    }

    //////////////////////////////////////////////组件相关///////////////////////////////////////////////////////////////


    @FXML
    void getClickComponent(MouseEvent event) {
        moveCanvas.getGraphicsContext2D().clearRect(0, 0, moveCanvas.getWidth(), moveCanvas.getHeight());
        if(null != componentList && componentList.size() > 0){
            drawComponents(drawCanvas, true, null);
            currentComponent = null;
            for(int i = componentList.size() - 1; i >= 0; i--){
                if(componentList.get(i).isMe(event.getX(), event.getY())){
                    currentComponent = componentList.get(i);
                    break;
                }
            }
            if(currentComponent != null){
                currentComponent.drawComponentBorder(drawCanvas);
                fillComponentControl(currentComponent);
                showComponentZone(currentComponent.getType());
            }else {
                showComponentZone(null);
            }
        }
    }

    @FXML
    void beginMove(MouseEvent event){
        if(currentComponent != null){
            offsetX = event.getX();
            offsetY = event.getY();
            baseX = currentComponent.getX();
            baseY = currentComponent.getY();
            if(currentComponent.getType() == BaseComponent.ComponentType.SHAPE){
                ShapeComponent component = (ShapeComponent) currentComponent;
                if(component.getShapeType().equals(PCStatusConstant.SHAPE_LINE)){
                    baseWidth = component.getWidth();
                    baseHeight = component.getHeight();
                }
            }
            drawComponents(drawCanvas, true, currentComponent);
            moveCanvas.getGraphicsContext2D().clearRect(0, 0, moveCanvas.getWidth(), moveCanvas.getHeight());
            currentComponent.drawComponent(moveCanvas.getGraphicsContext2D());
            currentComponent.drawComponentBorder(moveCanvas);
        }
    }

    @FXML
    void moveComponent(MouseEvent event){
        if(currentComponent != null){
            currentComponent.setX((int) (baseX + (event.getX() - offsetX)));
            currentComponent.setY((int) (baseY + (event.getY() - offsetY)));
            if(currentComponent.getType() == BaseComponent.ComponentType.SHAPE){
                ShapeComponent component = (ShapeComponent) currentComponent;
                if(component.getShapeType().equals(PCStatusConstant.SHAPE_LINE)){
                    component.setWidth((int) (baseWidth + (event.getX() - offsetX)));
                    component.setHeight((int) (baseHeight + (event.getY() - offsetY)));
                }
            }
            moveCanvas.getGraphicsContext2D().clearRect(0, 0, moveCanvas.getWidth(), moveCanvas.getHeight());
            currentComponent.drawComponent(moveCanvas.getGraphicsContext2D());
            currentComponent.drawComponentBorder(moveCanvas);
        }
    }

    @FXML
    void addComponent(ActionEvent event) {
        if(PCStatusConstant.defaultTemplateNames.contains(currentTemplateName)){
            showWarning("默认模板无法增加组件");
        }else {
            MonitorApplication.componentStage.show();
        }
    }

    @FXML
    void removeComponent(ActionEvent event) {
        if(PCStatusConstant.defaultTemplateNames.contains(currentTemplateName)){
            showWarning("无法删除默认模板的组件");
        }else {
            componentList.remove(currentComponent);
            currentComponent = null;
            showComponentZone(null);
            drawComponents(drawCanvas, true, null);
        }
    }

    @FXML
    void preComponent(ActionEvent event){
        int index = componentList.indexOf(currentComponent);
        if(index == 0){
            currentComponent = componentList.get(componentList.size() - 1);
        }else {
            currentComponent = componentList.get(index - 1);
        }
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
        showComponentZone(currentComponent.getType());
        fillComponentControl(currentComponent);
    }

    @FXML
    void nextComponent(ActionEvent event){
        int index = componentList.indexOf(currentComponent);
        if(index == (componentList.size() - 1)){
            currentComponent = componentList.get(0);
        }else {
            currentComponent = componentList.get(index + 1);
        }
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
        showComponentZone(currentComponent.getType());
        fillComponentControl(currentComponent);
    }

    @FXML
    void topComponent(ActionEvent event){
        componentList.remove(currentComponent);
        componentList.add(currentComponent);
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
    }

    @FXML
    void bottomComponent(ActionEvent event){
        componentList.remove(currentComponent);
        componentList.add(0, currentComponent);
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
    }

    @FXML
    void saveTextComponent(ActionEvent event) {
        if(StringUtils.isEmpty(textComponentContent.getText())){
            textComponentContent.setText("请输入内容");
        }
        TextComponent component = (TextComponent) currentComponent;
        component.setContent(textComponentContent.getText());
        component.setFillColor(textComponentFillColor.getValue());
        component.setStrokeColor(textComponentStrokeColor.getValue());
        component.setStroke(textComponentStroke.isSelected());
        if(StringUtils.isEmpty(textComponentFontSize.getText()) || Integer.parseInt(textComponentFontSize.getText()) < PCStatusConstant.MIN_FONT_SIZE){
            textComponentFontSize.setText("16");
        }
        component.setFontSize(Integer.parseInt(textComponentFontSize.getText()));
        if(StringUtils.isEmpty(textComponentX.getText())){
            textComponentX.setText("0");
        }
        component.setX(Integer.parseInt(textComponentX.getText()));
        if(StringUtils.isEmpty(textComponentY.getText())){
            textComponentY.setText("160");
        }
        component.setY(Integer.parseInt(textComponentY.getText()));
        component.setFontName(textComponentFontName.getValue());
        component.setAlignment(textComponentAlignment.getValue());
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
    }

    @FXML
    void saveImageComponent(ActionEvent event){
        ImageComponent component = (ImageComponent) currentComponent;
        if(StringUtils.isEmpty(imageComponentX.getText())){
            imageComponentX.setText("0");
        }
        if(StringUtils.isEmpty(imageComponentY.getText())){
            imageComponentY.setText("0");
        }
        if(StringUtils.isEmpty(imageComponentWidth.getText())){
            imageComponentWidth.setText("10");
        }else if(Integer.parseInt(imageComponentWidth.getText()) < 10){
            imageComponentWidth.setText("10");
        }
        if(StringUtils.isEmpty(imageComponentHeight.getText())){
            imageComponentHeight.setText("10");
        }else if(Integer.parseInt(imageComponentHeight.getText()) < 10){
            imageComponentHeight.setText("10");
        }
        component.setX(Integer.parseInt(imageComponentX.getText()));
        component.setY(Integer.parseInt(imageComponentY.getText()));
        component.setStretch(imageComponentStretch.isSelected());
        component.setWidth(Integer.parseInt(imageComponentWidth.getText()));
        component.setHeight(Integer.parseInt(imageComponentHeight.getText()));
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
    }

    @FXML
    void saveShapeComponent(ActionEvent event){
        ShapeComponent component = (ShapeComponent) currentComponent;
        if(StringUtils.isEmpty(shapeComponentArc.getText())){
            shapeComponentArc.setText("0");
        }
        if(StringUtils.isEmpty(shapeComponentLineWidth.getText())){
            shapeComponentLineWidth.setText("1");
        }else if(Integer.parseInt(shapeComponentLineWidth.getText()) <= 0){
            shapeComponentLineWidth.setText("1");
        }
        if(StringUtils.isEmpty(shapeComponentX.getText())){
            shapeComponentX.setText("0");
        }
        if(StringUtils.isEmpty(shapeComponentY.getText())){
            shapeComponentY.setText("0");
        }
        if(StringUtils.isEmpty(shapeComponentWidth.getText())){
            shapeComponentWidth.setText("10");
        }else if(Integer.parseInt(shapeComponentWidth.getText()) < 10){
            shapeComponentWidth.setText("10");
        }
        if(StringUtils.isEmpty(shapeComponentHeight.getText())){
            shapeComponentHeight.setText("10");
        }else if(Integer.parseInt(shapeComponentHeight.getText()) < 10){
            shapeComponentHeight.setText("10");
        }
        component.setShapeType(shapeComponentType.getValue());
        component.setColor(shapeComponentColor.getValue());
        component.setArc(Integer.parseInt(shapeComponentArc.getText()));
        component.setX(Integer.parseInt(shapeComponentX.getText()));
        component.setY(Integer.parseInt(shapeComponentY.getText()));
        component.setLineWidth(Integer.parseInt(shapeComponentLineWidth.getText()));
        component.setWidth(Integer.parseInt(shapeComponentWidth.getText()));
        component.setHeight(Integer.parseInt(shapeComponentHeight.getText()));
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
    }

    @FXML
    void saveBarComponent(ActionEvent event){
        BarComponent component = (BarComponent) currentComponent;
        if(StringUtils.isEmpty(barComponentBorderWidth.getText())){
            barComponentBorderWidth.setText("1");
        }else if(Integer.parseInt(barComponentBorderWidth.getText()) <= 0){
            barComponentBorderWidth.setText("1");
        }
        if(StringUtils.isEmpty(barComponentArc.getText())){
            barComponentArc.setText("0");
        }
        if(StringUtils.isEmpty(barComponentX.getText())){
            barComponentX.setText("0");
        }
        if(StringUtils.isEmpty(barComponentY.getText())){
            barComponentY.setText("0");
        }
        if(StringUtils.isEmpty(barComponentWidth.getText())){
            barComponentWidth.setText("50");
        }else if(Integer.parseInt(barComponentWidth.getText()) < 50){
            barComponentWidth.setText("50");
        }else if(Integer.parseInt(barComponentWidth.getText()) > 480){
            barComponentWidth.setText("480");
        }
        if(StringUtils.isEmpty(barComponentHeight.getText())){
            barComponentHeight.setText("4");
        }else if(Integer.parseInt(barComponentHeight.getText()) < 4){
            barComponentHeight.setText("4");
        }else if(Integer.parseInt(barComponentHeight.getText()) > 480){
            barComponentHeight.setText("480");
        }
        component.setStyle(barComponentStyle.getValue());
        if(component.getStyle().equals(PCStatusConstant.BAR_STYLE_1)){
            component.setBorderWidth(Integer.parseInt(barComponentBorderWidth.getText()));
        }else {
            component.setBorderWidth(1);
        }
        component.setBorderColor(barComponentBorderColor.getValue());
        component.setDirection(barComponentDirection.getValue());
        component.setArc(Integer.parseInt(barComponentArc.getText()));
        component.setColor(barComponentBarColor.getValue());
        component.setX(Integer.parseInt(barComponentX.getText()));
        component.setY(Integer.parseInt(barComponentY.getText()));
        component.setWidth(Integer.parseInt(barComponentWidth.getText()));
        component.setHeight(Integer.parseInt(barComponentHeight.getText()));
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
    }

    @FXML
    void saveDataComponent(ActionEvent event){
        DataComponent component = (DataComponent) currentComponent;
        component.setUnit(dataComponentUnit.isSelected());
        component.setColor(dataComponentFillColor.getValue());
        component.setFontName(dataComponentFontName.getValue());
        component.setAlignment(dataComponentAlignment.getValue());
        if(StringUtils.isEmpty(dataComponentX.getText())){
            dataComponentX.setText("0");
        }
        component.setX(Integer.parseInt(dataComponentX.getText()));
        if(StringUtils.isEmpty(dataComponentY.getText())){
            dataComponentY.setText("160");
        }
        component.setY(Integer.parseInt(dataComponentY.getText()));
        if(StringUtils.isEmpty(dataComponentFontSize.getText())){
            dataComponentFontSize.setText("16");
        }else if(Integer.parseInt(dataComponentFontSize.getText()) < 16){
            dataComponentFontSize.setText("16");
        }else if(Integer.parseInt(dataComponentFontSize.getText()) > 100){
            dataComponentFontSize.setText("100");
        }
        component.setFontSize(Integer.parseInt(dataComponentFontSize.getText()));
        drawComponents(drawCanvas, true, null);
        currentComponent.drawComponentBorder(drawCanvas);
    }

    @FXML
    void insertImage(ActionEvent event){
        FileChooser fc = new FileChooser();
        fc.setTitle("选择图片");
        FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("图片 ( .jpg  .jpeg  .png )",
                "*.jpg", "*.jpeg", "*.png");
        fc.getExtensionFilters().add(extFilter);
        File file = fc.showOpenDialog(root.getScene().getWindow());
        if (file != null) {
            ImageComponent component = (ImageComponent) currentComponent;
            Image image = new Image(file.toURI().toString());
            component.setImagePath(file.getPath());
            component.setImageName(file.getName());
            component.setWidth((int)image.getWidth());
            component.setHeight((int)image.getHeight());
            component.setImage(image);
            imageComponentPath.setText(component.getImagePath());
            imageComponentHeight.setText(component.getHeight() + "");
            imageComponentWidth.setText(component.getWidth() + "");
            if(!componentList.contains(component)){
                componentList.add(component);
            }
            drawComponents(drawCanvas, true, null);
            component.drawComponentBorder(drawCanvas);
        }
    }

    public void generateComponent(String componentType, String componentName){
        if(!componentType.equals(PCStatusConstant.COMPONENT_TEXT) && !componentType.equals(PCStatusConstant.COMPONENT_IMAGE) && !componentType.equals(PCStatusConstant.COMPONENT_SHAPE) && null != componentList && componentList.size() > 0){
            for (BaseComponent baseComponent : componentList) {
                if(baseComponent.getType() == BaseComponent.ComponentType.DATA && !componentType.equals(PCStatusConstant.COMPONENT_BAR)){
                    DataComponent component = (DataComponent) baseComponent;
                    if(component.getName().equals(componentName)){
                        showWarning("组件【" + componentName + "】已插入");
                        return;
                    }
                }else if(baseComponent.getType() == BaseComponent.ComponentType.BAR && componentType.equals(PCStatusConstant.COMPONENT_BAR)){
                    BarComponent component = (BarComponent) baseComponent;
                    if(component.getName().equals(componentName)){
                        showWarning("关联【" + componentName + "】的条形组件已插入");
                        return;
                    }
                }
            }
        }
        if(componentType.equals(PCStatusConstant.COMPONENT_TEXT)){
            showComponentZone(BaseComponent.ComponentType.TEXT);
            TextComponent component = new TextComponent();
            component.setType(BaseComponent.ComponentType.TEXT);
            component.setContent("请输入内容");
            component.setFillColor(textComponentFillColor.getValue());
            component.setStrokeColor(textComponentStrokeColor.getValue());
            component.setAlignment(textComponentAlignment.getValue());
            component.setStroke(false);
            component.setFontName(textComponentFontName.getValue());
            component.setFontSize(Integer.parseInt(textComponentFontSize.getText()));
            component.setX(240);
            component.setY(160);
            doAfterCreateDefaultComponent(component);
        }else if(componentType.equals(PCStatusConstant.COMPONENT_IMAGE)){
            showComponentZone(BaseComponent.ComponentType.IMAGE);
            ImageComponent component = new ImageComponent();
            component.setType(BaseComponent.ComponentType.IMAGE);
            component.setX(0);
            component.setY(0);
            component.setStretch(false);
            doAfterCreateDefaultComponent(component);
        }else if(componentType.equals(PCStatusConstant.COMPONENT_SHAPE)){
            showComponentZone(BaseComponent.ComponentType.SHAPE);
            ShapeComponent component = new ShapeComponent();
            component.setType(BaseComponent.ComponentType.SHAPE);
            component.setShapeType(shapeComponentType.getValue());
            component.setColor(shapeComponentColor.getValue());
            component.setX(240);
            component.setY(160);
            component.setWidth(100);
            component.setHeight(100);
            component.setArc(0);
            component.setLineWidth(1);
            doAfterCreateDefaultComponent(component);
        }else if(componentType.equals(PCStatusConstant.COMPONENT_BAR)){
            showComponentZone(BaseComponent.ComponentType.BAR);
            BarComponent component = new BarComponent();
            component.setType(BaseComponent.ComponentType.BAR);
            component.setName(componentName);
            component.setBorderWidth(Integer.parseInt(barComponentBorderWidth.getText()));
            component.setBorderColor(barComponentBorderColor.getValue());
            component.setDirection(barComponentDirection.getValue());
            component.setStyle(barComponentStyle.getValue());
            component.setArc(Integer.parseInt(barComponentArc.getText()));
            component.setColor(barComponentBarColor.getValue());
            component.setWidth(Integer.parseInt(barComponentWidth.getText()));
            component.setHeight(Integer.parseInt(barComponentHeight.getText()));
            component.setX(240);
            component.setY(160);
            doAfterCreateDefaultComponent(component);
        }else{
            showComponentZone(BaseComponent.ComponentType.DATA);
            DataComponent component = new DataComponent();
            component.setType(BaseComponent.ComponentType.DATA);
            component.setName(componentName);
            component.setColor(dataComponentFillColor.getValue());
            component.setFontName(dataComponentFontName.getValue());
            component.setAlignment(dataComponentAlignment.getValue());
            component.setUnit(true);
            component.setFontSize(Integer.parseInt(dataComponentFontSize.getText()));
            component.setX(240);
            component.setY(160);
            doAfterCreateDefaultComponent(component);
        }
    }

    private void setSettingOptionsVisiable(boolean b){
        customZone.setVisible(b);
        saveTemplateBtn.setVisible(b);
        synchronousScreenBtn.setVisible(b);
        baseCanvas.setVisible(b);
        drawCanvas.setVisible(b);
        customZoneLabel.setVisible(!b);
    }

    private void drawComponents(Canvas canvas, boolean clear, BaseComponent missedComponent){
        GraphicsContext gc = canvas.getGraphicsContext2D();
        if(clear){
            gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
        }
        if(componentList.size() > 0){
            ArrayList<BaseComponent> components = new ArrayList<>(); // 保存需要循环发送的组件,先将文字组件、形状组件、图片组件绘制完毕之后，再绘制数据组件和条形组件
            for (BaseComponent baseComponent : componentList) {
                if(baseComponent == missedComponent){
                    continue;
                }
                if(baseComponent.getType() == BaseComponent.ComponentType.TEXT
                        || baseComponent.getType() == BaseComponent.ComponentType.IMAGE
                        || baseComponent.getType() == BaseComponent.ComponentType.SHAPE){
                    baseComponent.drawComponent(gc);
                }else {
                    components.add(baseComponent);
                }
            }
            for (BaseComponent component : components) {
                component.drawComponent(gc);
            }
        }
    }

    private void drawFixedComponents(){
        GraphicsContext gc = baseCanvas.getGraphicsContext2D();
        if (componentList.size() > 0){
            for (BaseComponent component : componentList) {
                if(component.getType() == BaseComponent.ComponentType.TEXT
                || component.getType() == BaseComponent.ComponentType.IMAGE
                || component.getType() == BaseComponent.ComponentType.SHAPE){
                    component.drawComponent(gc);
                }
                if((component.getType() == BaseComponent.ComponentType.DATA)){
                    DataComponent dataComponent = (DataComponent) component;
                    if(PCStatusConstant.drawBackImageList.contains(dataComponent.getName())){
                        dataComponent.drawComponent(gc);
                    }
                }
            }
        }
    }

    private void fillComponentControl(BaseComponent baseComponent){
        if(baseComponent.getType() == BaseComponent.ComponentType.TEXT){
            TextComponent component = (TextComponent) baseComponent;
            textComponentContent.setText(component.getContent());
            textComponentFillColor.setValue(component.getFillColor());
            textComponentFontName.setValue(component.getFontName());
            textComponentAlignment.setValue(component.getAlignment());
            textComponentFontSize.setText(component.getFontSize() + "");
            textComponentStroke.setSelected(component.isStroke());
            textComponentStrokeColor.setValue(component.getStrokeColor());
            textComponentX.setText(component.getX() + "");
            textComponentY.setText(component.getY() + "");
        }else if(baseComponent.getType() == BaseComponent.ComponentType.IMAGE){
            ImageComponent component = (ImageComponent) baseComponent;
            imageComponentX.setText(component.getX() + "");
            imageComponentY.setText(component.getY() + "");
            imageComponentHeight.setText(component.getHeight() + "");
            imageComponentWidth.setText(component.getWidth() + "");
            imageComponentPath.setText(component.getImagePath());
            imageComponentStretch.setSelected(component.isStretch());
        }else if(baseComponent.getType() == BaseComponent.ComponentType.SHAPE){
            ShapeComponent component = (ShapeComponent) baseComponent;
            shapeComponentArc.setText(component.getArc() + "");
            shapeComponentLineWidth.setText(component.getLineWidth() + "");
            shapeComponentColor.setValue(component.getColor());
            shapeComponentType.setValue(component.getShapeType());
            shapeComponentX.setText(component.getX() + "");
            shapeComponentY.setText(component.getY() + "");
            shapeComponentWidth.setText(component.getWidth() + "");
            shapeComponentHeight.setText(component.getHeight() + "");
        }else if(baseComponent.getType() == BaseComponent.ComponentType.BAR){
            BarComponent component = (BarComponent) baseComponent;
            barComponentName.setText(component.getName());
            barComponentBorderWidth.setText(component.getBorderWidth() + "");
            barComponentBorderColor.setValue(component.getBorderColor());
            barComponentDirection.setValue(component.getDirection());
            barComponentStyle.setValue(component.getStyle());
            barComponentArc.setText(component.getArc() + "");
            barComponentBarColor.setValue(component.getColor());
            barComponentWidth.setText(component.getWidth() + "");
            barComponentHeight.setText(component.getHeight() + "");
            barComponentX.setText(component.getX() + "");
            barComponentY.setText(component.getY() + "");
            if(barComponentStyle.getValue().equals(PCStatusConstant.BAR_STYLE_1)){
                barComponentBorderWidth.setVisible(true);
                barComponentBorderWidthLabel.setVisible(true);
            }else {
                barComponentBorderWidth.setVisible(false);
                barComponentBorderWidthLabel.setVisible(false);
            }
        }else {
            DataComponent component = (DataComponent) baseComponent;
            dataComponentName.setText(component.getName());
            dataComponentFillColor.setValue(component.getColor());
            dataComponentFontName.setValue(component.getFontName());
            dataComponentAlignment.setValue(component.getAlignment());
            dataComponentFontSize.setText(component.getFontSize() + "");
            dataComponentUnit.setSelected(component.isUnit());
            dataComponentX.setText(component.getX() + "");
            dataComponentY.setText(component.getY() + "");
            if(PCStatusConstant.notUnitCheckboxList.contains(component.getName())){
                dataComponentUnit.setVisible(false);
            }else {
                dataComponentUnit.setVisible(true);
            }
        }
    }

    private void showComponentZone(BaseComponent.ComponentType componentType){
        textComponentZone.setVisible(false);
        imageComponentZone.setVisible(false);
        shapeComponentZone.setVisible(false);
        animComponentZone.setVisible(false);
        barComponentZone.setVisible(false);
        dataComponentZone.setVisible(false);
        removeComponentBtn.setVisible(false);
        preComponentBtn.setVisible(false);
        nextComponentBtn.setVisible(false);
        if(componentType == null){
            topComponentBtn.setVisible(false);
            bottomComponentBtn.setVisible(false);
            return;
        }
        topComponentBtn.setVisible(true);
        bottomComponentBtn.setVisible(true);
        removeComponentBtn.setVisible(true);
        preComponentBtn.setVisible(true);
        nextComponentBtn.setVisible(true);
        if(componentType == BaseComponent.ComponentType.TEXT){
            textComponentZone.setVisible(true);
        }else if(componentType == BaseComponent.ComponentType.IMAGE){
            imageComponentZone.setVisible(true);
        }else if(componentType == BaseComponent.ComponentType.SHAPE){
            shapeComponentZone.setVisible(true);
        }else if(componentType == BaseComponent.ComponentType.BAR){
            topComponentBtn.setVisible(false);
            bottomComponentBtn.setVisible(false);
            barComponentZone.setVisible(true);
        }else if(componentType == BaseComponent.ComponentType.DATA){
            dataComponentZone.setVisible(true);
            topComponentBtn.setVisible(false);
            bottomComponentBtn.setVisible(false);
        }
    }

    private void doAfterCreateDefaultComponent(BaseComponent component){
        currentComponent = component;
        fillComponentControl(component);
        if(component.getType() != BaseComponent.ComponentType.IMAGE){
            componentList.add(component);
        }
        drawComponents(drawCanvas, true, null);
        component.drawComponentBorder(drawCanvas);
    }

    //////////////////////////////////////////////传感器页面///////////////////////////////////////////////////////////////


    public void showInfos() {
        Platform.runLater(() -> {
            DecimalFormat df = new DecimalFormat("0.0");
            cpuName.setText(HardWareInfo.cpuName);
            cpuUsageCur.setText(HardWareInfo.cpuUsageCur + "%");
            cpuUsageMax.setText(HardWareInfo.cpuUsageMax + "%");
            cpuUsageMin.setText(HardWareInfo.cpuUsageMin + "%");
            cpuTempCur.setText(HardWareInfo.cpuTempCur + "℃");
            cpuTempMin.setText(HardWareInfo.cpuTempMin + "℃");
            cpuTempMax.setText(HardWareInfo.cpuTempMax + "℃");
            cpuClockCur.setText(HardWareInfo.cpuClockCur + "MHz");
            cpuClockMin.setText(HardWareInfo.cpuClockMin + "MHz");
            cpuClockMax.setText(HardWareInfo.cpuClockMax + "MHz");
            cpuPowerCur.setText(df.format(HardWareInfo.cpuPowerCur) + "W");
            cpuPowerMin.setText(df.format(HardWareInfo.cpuPowerMin) + "W");
            cpuPowerMax.setText(df.format(HardWareInfo.cpuPowerMax) + "W");
            gpuName.setText(HardWareInfo.gpuName);
            gpuUsageCur.setText(HardWareInfo.gpuUsageCur + "%");
            gpuUsageMax.setText(HardWareInfo.gpuUsageMax + "%");
            gpuUsageMin.setText(HardWareInfo.gpuUsageMin + "%");
            gpuTempCur.setText(HardWareInfo.gpuTempCur + "℃");
            gpuTempMin.setText(HardWareInfo.gpuTempMin + "℃");
            gpuTempMax.setText(HardWareInfo.gpuTempMax + "℃");
            gpuClockCur.setText(HardWareInfo.gpuClockCur + "MHz");
            gpuClockMin.setText(HardWareInfo.gpuClockMin + "MHz");
            gpuClockMax.setText(HardWareInfo.gpuClockMax + "MHz");
            gpuPowerCur.setText(df.format(HardWareInfo.gpuPowerCur) + "W");
            gpuPowerMin.setText(df.format(HardWareInfo.gpuPowerMin) + "W");
            gpuPowerMax.setText(df.format(HardWareInfo.gpuPowerMax) + "W");
            memUsed.setText(HardWareInfo.memUsed + "%");
            memName.setText(HardWareInfo.memName);
            memClock.setText(HardWareInfo.memClock + "MHz");
            if(HardWareInfo.netUploadSpeed < 100){
                netUploadSpeed.setText(df.format(HardWareInfo.netUploadSpeed) + "K/s");
            }else if(HardWareInfo.netUploadSpeed < 1000){
                netUploadSpeed.setText((int)HardWareInfo.netUploadSpeed + "K/s");
            }else {
                netUploadSpeed.setText(df.format(HardWareInfo.netUploadSpeed / 1024) + "M/s");
            }
            if(HardWareInfo.netDownloadSpeed < 100){
                netDownloadSpeed.setText(df.format(HardWareInfo.netDownloadSpeed) + "K/s");
            }else if(HardWareInfo.netDownloadSpeed < 1000){
                netDownloadSpeed.setText((int)HardWareInfo.netDownloadSpeed + "K/s");
            }else {
                netDownloadSpeed.setText(df.format(HardWareInfo.netDownloadSpeed / 1024) + "M/s");
            }
        });
    }

    @FXML
    void clearValue(MouseEvent event) {
        HardWareInfo.cpuTempMin = HardWareInfo.cpuTempCur;
        HardWareInfo.cpuTempMax = HardWareInfo.cpuTempCur;
        HardWareInfo.cpuUsageMin = HardWareInfo.cpuUsageCur;
        HardWareInfo.cpuUsageMax = HardWareInfo.cpuUsageCur;
        HardWareInfo.cpuClockMin = HardWareInfo.cpuClockCur;
        HardWareInfo.cpuClockMax = HardWareInfo.cpuClockCur;
        HardWareInfo.cpuPowerMin = HardWareInfo.cpuPowerCur;
        HardWareInfo.cpuPowerMax = HardWareInfo.cpuPowerCur;
        HardWareInfo.gpuTempMin = HardWareInfo.gpuTempCur;
        HardWareInfo.gpuTempMax = HardWareInfo.gpuTempCur;
        HardWareInfo.gpuUsageMin = HardWareInfo.gpuUsageCur;
        HardWareInfo.gpuUsageMax = HardWareInfo.gpuUsageCur;
        HardWareInfo.gpuClockMin = HardWareInfo.gpuClockCur;
        HardWareInfo.gpuClockMax = HardWareInfo.gpuClockCur;
        HardWareInfo.gpuPowerMin = HardWareInfo.gpuPowerCur;
        HardWareInfo.gpuPowerMax = HardWareInfo.gpuPowerCur;
        showInfos();
    }

    //////////////////////////////////////////////首选项页面///////////////////////////////////////////////////////////////

    @FXML
    void autoStartAction(ActionEvent event) {
        showWarning("开源版本暂未开发此功能");
    }

    @FXML
    void systemTrayAction(ActionEvent event) {
        showWarning("开源版本暂未开发此功能");
    }

    private void changeTheme() {
        Platform.runLater(() -> {
            MonitorApplication.scene.getStylesheets().clear();
            MonitorApplication.componentScene.getStylesheets().clear();
            MonitorApplication.scene.getStylesheets().add(MonitorApplication.cssUrl.toExternalForm());
            MonitorApplication.componentScene.getStylesheets().add(MonitorApplication.cssUrl.toExternalForm());
        });
    }

    @FXML
    void comRefresh(ActionEvent event){
        List<String> ports = SerialPortManager.findPorts();
        if(null != ports && ports.size() > 0){
            comChoose.setItems(FXCollections.observableArrayList(ports));
        }
        showRight("已重新加载所有端口");
    }

    @FXML
    void connectSerial(ActionEvent event) {
        if(MonitorApplication.serialport != null){
            comBtn.setDisable(true);
            MonitorApplication.passNormalData.set(false);
            try {
                FileUtil.updateKey("port", "");
                SerialPortManager.closePort(MonitorApplication.serialport);
                MonitorApplication.serialport = null;
                MonitorApplication.settingConfig.setPort("");
                comBtn.setText("连接");
                comChoose.setDisable(false);
                comBtn.setDisable(false);
                comRefreshBtn.setDisable(false);
            } catch (Exception e) {
                showWarning("断开失败，请重试");
            }
        }else {
            String port = comChoose.getSelectionModel().getSelectedItem();
            if(port == null || port.equals("")){
                showWarning("请先选择一个端口");
                return;
            }
            try {
                MonitorApplication.serialport = SerialPortManager.openPort(port, PCStatusConstant.BAUD_RATE);
                if(MonitorApplication.serialport != null){
                    comBtn.setText("断开");
                    comChoose.setDisable(true);
                    FileUtil.updateKey("monitor.port", port);
                    addSerialListener(MonitorApplication.serialport);
                    HardWareInfo.refreshAll = true;
                    MonitorApplication.passNormalData.set(true);
                }
            } catch (Exception e) {
                showWarning("连接端口失败");
            }
        }
    }

    @FXML
    void sendLight(ActionEvent event) {
        if(autoLight.isSelected()){
            MonitorApplication.settingConfig.setAutoLight(true);
            try {
                FileUtil.updateKey("autoLight", "true");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if(MonitorApplication.serialport == null){
                showWarning("副屏端口尚未连接");
            }else {
                byte[] msg = new byte[]{(byte) 255, 12, 34, PCStatusConstant.MSG_BRIGHT, 0 , 43, 21, (byte) 255};
                MonitorApplication.priorityDataArray.offer(msg);
                showRight("亮度调节命令已发送");
            }
        }else {
            int newLight = (int) lightSlider.getValue();
            MonitorApplication.settingConfig.setLight(newLight);
            MonitorApplication.settingConfig.setAutoLight(false);
            try {
                FileUtil.updateKey("light", newLight + "");
                FileUtil.updateKey("autoLight", "false");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if(MonitorApplication.serialport == null){
                showWarning("副屏端口尚未连接");
            }else {
                byte[] msg = new byte[]{(byte) 255, 12, 34, PCStatusConstant.MSG_BRIGHT, (byte) newLight, 43, 21, (byte) 255};
                MonitorApplication.priorityDataArray.offer(msg);
                showRight("亮度调节命令已发送");
            }
        }
    }

    @FXML
    void autoLightAction(ActionEvent event){
        if(autoLight.isSelected()){
            lightSlider.setDisable(true);
        }else {
            lightSlider.setDisable(false);
        }
    }

    @FXML
    void checkKey(ActionEvent event) {
        String key = weatherKey.getText();
        String name = cityName.getText();
        if(key.trim().equals("") || name.trim().equals("")){
            Platform.runLater(() -> {
                showWarning("请输入 KEY 和 城市名称");
            });
        }else {
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder().url(PCStatusConstant.CITI_URL + key + "&location=" + name).build();
            loading = new Alert(Alert.AlertType.INFORMATION);
            loading.initOwner(root.getScene().getWindow());
            loading.initStyle(StageStyle.TRANSPARENT);
            loading.getDialogPane().setPrefWidth(200);
            loading.setHeaderText("");
            loading.setContentText("处理中，请稍后...");
            loading.setGraphic(new ImageView("/image/loading.png"));
            Button btn = (Button) loading.getDialogPane().lookupButton(ButtonType.OK);
            btn.setDisable(true);
            btn.setText("OK");
            loading.show();
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Platform.runLater(() -> {
                        loading.close();
                        showWarning("网络异常，操作失败");
                    });
                }
                @Override
                public void onResponse(Call call, Response response){
                    if (!response.isSuccessful()){
                        Platform.runLater(() -> {
                            loading.close();
                            showWarning("网络异常，操作失败");
                        });
                    }else {
                        try {
                            String s = new String(response.body().bytes(), "utf-8");
                            HefengQueryCityInfo cityInfo = JSONObject.parseObject(s, HefengQueryCityInfo.class);
                            String code = cityInfo.getCode();
                            if(code.equals("200")){
                                HefengQueryCityInfo.LocationEntity location = cityInfo.getLocation().get(0);
                                MonitorApplication.settingConfig.setCityName(location.getName());
                                MonitorApplication.settingConfig.setCityID(location.getId());
                                MonitorApplication.settingConfig.setKey(key);
                                cityName.setText(MonitorApplication.settingConfig.getCityName());
                                cityID.setText(MonitorApplication.settingConfig.getCityID());
                                HardWareInfo.cityName = MonitorApplication.settingConfig.getCityName();
                                FileUtil.updateWeatherConfigs(MonitorApplication.settingConfig.getKey(), MonitorApplication.settingConfig.getCityName(), MonitorApplication.settingConfig.getCityID());
                                Platform.runLater(() -> {
                                    loading.close();
                                    showRight("绑定成功");
                                    MonitorApplication.taskExecutor.execute(new WeatherTask(MonitorApplication.settingConfig.getKey(), MonitorApplication.settingConfig.getCityID(), MonitorApplication.mainController, MonitorApplication.taskExecutor));
                                });
                            }else {
                                String msg;
                                if(code.equals("404")){
                                    msg = "该城市不存在";
                                }else if(code.equals("402")){
                                    msg = "今日已无访问次数";
                                }else if(code.equals("500")){
                                    msg = "接口服务异常";
                                }else {
                                    msg = "无效的KEY";
                                }
                                Platform.runLater(() -> {
                                    loading.close();
                                    showWarning(msg);
                                });
                            }
                        } catch (Exception e) {
                            Platform.runLater(() -> {
                                loading.close();
                                showWarning("发生错误，请重试");
                            });
                        }
                    }
                }
            });
        }
    }

    /////////////////////////////////////////////////其他/////////////////////////////////////////////////////////////////


    public void showWarning(String message){
        Alert alert = new Alert(Alert.AlertType.WARNING);
        alert.initOwner(root.getScene().getWindow());
        alert.setHeaderText("");
        alert.setTitle(" 警告");
        alert.setContentText(message);
        alert.setGraphic(new ImageView("/image/warning.png"));
        alert.showAndWait();
    }

    public void showRight(String message){
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.initOwner(root.getScene().getWindow());
        alert.setHeaderText("");
        alert.setTitle(" 提示");
        alert.setContentText(message);
        alert.setGraphic(new ImageView("/image/right.png"));
        alert.showAndWait();
    }

    private void addSerialListener(SerialPort serialPort){
        SerialPortManager.addListener(serialPort, () -> {
            byte[] data = null;
            try {
                if (serialPort == null) {
                    System.out.println("串口对象为空，监听失败！");
                } else {
                    data = SerialPortManager.readFromPort(serialPort);
                    String response = new String(data);
                    response = response.substring(response.length() - 3);
                    MonitorApplication.msgOK.set(true);
                    if(response.equals(PCStatusConstant.RESPONSE_OK)){
                        MonitorApplication.msgAnswer = PCStatusConstant.RESPONSE_OK;
                    }else if(new String(data).equals(PCStatusConstant.RESPONSE_WRONG)){
                        MonitorApplication.msgAnswer = PCStatusConstant.RESPONSE_WRONG;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                if(MonitorApplication.serialport != null){
                    Platform.runLater(() -> {
                        comBtn.setText("连接");
                        comChoose.setDisable(false);
                    });
                    SerialPort serialport = MonitorApplication.serialport;
                    MonitorApplication.serialport = null;
                    SerialPortManager.closePort(serialport);
                }
            }
        });
    }

    private ArrayList<BaseComponent> getCommunicationComponentList(List<BaseComponent> list){
        ArrayList<BaseComponent> result = new ArrayList<>();
        if(list.size() > 0){
            for (BaseComponent component : list) {
                if(component.getType() == BaseComponent.ComponentType.BAR){
                    result.add(component);
                }
                if(component.getType() == BaseComponent.ComponentType.DATA){
                    DataComponent dataComponent = (DataComponent) component;
                    if(!PCStatusConstant.drawBackImageList.contains(dataComponent.getName())){
                        result.add(component);
                    }
                }
            }
        }
        return result;
    }

    private ArrayList<BaseComponent> getCoincidenceVerificationComponentList(List<BaseComponent> list){
        ArrayList<BaseComponent> result = new ArrayList<>();
        if(list.size() > 0){
            for (BaseComponent component : list) {
                if(component.getType() == BaseComponent.ComponentType.BAR){
                    result.add(component);
                }
                if(component.getType() == BaseComponent.ComponentType.DATA){
                    DataComponent dataComponent = (DataComponent) component;
                    if(!PCStatusConstant.drawBackImageList.contains(dataComponent.getName())){
                        result.add(component);
                    }
                }
            }
        }
        return result;
    }

}
